-
Couldn't load subscription status.
- Fork 441
Allow post-validation FromInputValue errors
#987
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
cc @ilslv Before continuing this, make sure |
# Conflicts: # juniper/src/ast.rs # juniper_actix/src/lib.rs
|
@tyranron PR is ready for review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ilslv I've refactored base machinery in juniper:
- more errors propagation;
- simplifying code with using
Stringin implementations rather thanFieldError<S>.
Codegen needs some updates, though, described below.
juniper/src/types/containers.rs
Outdated
| NotEnough(usize), | ||
|
|
||
| /// Too many elements. Contains __all__ [`InputValue`] elements. | ||
| TooMuch(Vec<T>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do think keeping Vec gives no actual use here, while complicates relative unsafe code (and so reasoning) a lot.
| <Vec<i32>>::from_input_value(&V::list(vec![V::scalar(1), V::scalar(2), V::scalar(3)])), | ||
| Ok(vec![1, 2, 3]), | ||
| ); | ||
| // TODO: all examples |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ilslv we should provide here a complete test suite. But let's do it in a separate PR after merging this.
juniper/src/schema/meta.rs
Outdated
| T: FromInputValue<S>, | ||
| { | ||
| <T as FromInputValue<S>>::from_input_value(v).is_some() | ||
| T::from_input_value(v).is_ok() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't actually propagate any errors here, only silence them as we did before. Let's do propagation.
juniper/src/types/scalars.rs
Outdated
| .map(ID), | ||
| _ => None, | ||
| } | ||
| fn from_input_value(v: &InputValue) -> Result<ID, FieldError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be more accurate here and use FieldError<S> to omit redundant scalar conversions.
| } | ||
| } | ||
| None => return Box::pin(::juniper::futures::future::ready( | ||
| Err(::juniper::FieldError::from("This GraphQLType has no name")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ilslv to DRYing the generated code a bit, let's move such things to helper functions inside juniper crate, and reuse them here.
…nput-value-resolve-errors # Conflicts: # juniper/CHANGELOG.md
# Conflicts: # integration_tests/juniper_tests/src/issue_372.rs # juniper/CHANGELOG.md # juniper/src/validation/rules/fields_on_correct_type.rs # juniper_actix/src/lib.rs
|
@tyranron this PR is ready for review |
| }, | ||
| Ok, | ||
| ) | ||
| })? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ilslv I don't follow the logic here.
It was:
args.get::<#ty>(#name)returnsOption<T>.- If it's
None, then::juniper::FromInputValue::<#scalar>::from_implicit_nullreturnsOption<T>. - If it's
Nonewe panic.
Now it is:
args.get::<#ty>(#name)returnsResult<Option<T>, FieldError>.- If it's
Ok, we check the inneropt. - If it
Somewe map it toSome(Ok(v))and so haveResult<Option<Result<T>, FieldError>, FieldError>.
Why?
It seems the more natural way is:
- Unpack the
Resultearly:args.get::<#ty>(#name)? .transpose()the inner error inOptionand return it with?.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh... understood. .map_or_else doesn't map an inner Option value, but rather maps the whole Option into something.
.ok_or_else will do better here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meh... .ok_or_else() cannot map absense to Result::Ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ilslv LGTM
| let e = ::juniper::IntoFieldError::into_field_error(e); | ||
| ::juniper::FieldError::new( | ||
| format!(#err_text, e.message()), | ||
| e.extensions().clone(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This mess is better be replaced with .map_message method on FieldError.
| }, | ||
| Ok, | ||
| ) | ||
| })? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meh... .ok_or_else() cannot map absense to Result::Ok.
Required for #975
Synopsis
At the moment,
FromInputValuefallibility is considered during input operation validation only. Also, the real error is erased, due toOption<T>usage, thus argument absence is unobviously mixed with convertion errors over the code base.Being applicable to most cases, still there are some situations where the error may occur only during resolution after passing the validation (from #975 it's deserializing
json::ValueintoJson<T: Deserialize>). At the moment, we're ending up with runtime panics in such situation, which is not good.Solution
Make
FromInputValuereturningResultwith the actual error preservation. Require this error beIntoFieldErrorconvertible, so it may naturally bubble-up during operation execution.Checklist